import { compareTwoVdom, findDOM } from './react-dom'

export const updateQueue = {
  isBatchingUpdate: false, // 通过此变量控制是否时批量更新
  updaters: [],
  batchUpdate() {
    for (const updater of updateQueue.updaters) {
      updater.updateComponent()
    }
    updateQueue.isBatchingUpdate = false
    updateQueue.updaters.length = 0
  },
}

class Updater {
  constructor(classInstance) {
    this.classInstance = classInstance
    this.pendingStates = []
    this.callbacks = []
  }

  addState(partialState, callback) {
    this.pendingStates.push(partialState)
    if (typeof callback === 'function') {
      this.callbacks.push(callback)
    }
    this.emitUpdate()
  }
  emitUpdate(nextProps) {
    this.nextProps = nextProps // 可能会传过来一些新的属性对象
    // 如果是批量更新，将当前实例插入到updaters
    if (updateQueue.isBatchingUpdate) {
      updateQueue.updaters.push(this)
    } else {
      this.updateComponent()
    }
  }
  updateComponent() {
    const { classInstance, nextProps, pendingStates } = this
    if (nextProps || pendingStates.length > 0) {
      shouldUpdate(classInstance, nextProps, this.getState())
    }
  }
  getState() {
    const { classInstance, pendingStates } = this
    console.log(classInstance)
    let { state } = classInstance
    pendingStates.forEach((nextState) => {
      if (typeof nextState === 'function') {
        state = nextState(state)
      } else {
        state = { ...state, ...nextState }
      }
    })
    pendingStates.length = 0
    return state
  }
}

function shouldUpdate(classInstance, nextProps, nextState) {
  let willUpdate = true
  if (classInstance.shouldComponent && !classInstance.shouldComponent()) {
    willUpdate = false
  }
  if (willUpdate && classInstance.componentWillUpdate) {
    classInstance.componentWillUpdate()
  }
  if (nextProps) classInstance.props = nextProps
  classInstance.state = nextState
  if (willUpdate) {
    classInstance.forceUpdate()
  }
}

class Component {
  static isReactComponent = true
  constructor(props) {
    this.props = props
    this.state = {}
    this.updater = new Updater(this)
  }

  setState(partialState, callback) {
    this.updater.addState(partialState, callback)
  }

  /**
   * 1. 获取老得虚拟Dom
   * 2. 根据最新的状态和属性获取新的虚拟Dom
   * 3. 比较新老虚拟DOm，暂时把原来的直接替换掉
   */
  forceUpdate() {
    const oldRenderVdom = this.oldRenderVdom
    const oldDOM = findDOM(oldRenderVdom)
    const newRenderVdom = this.render()
    compareTwoVdom(oldDOM.parentNode, oldRenderVdom, newRenderVdom)
    this.oldRenderVdom = newRenderVdom
  }
}

export default Component
